MS-DOS:1.25:Z-100 OEM:1.01:8-11-1983/disk02/BCLOCK.ASM
Clock subroutines assembler source file. File content ; ; BIOS_SETDATE - Set the date ; ; Call with: ; AX = the number of days since Jan 1, 1980. ; ; Uses: No registers are used. ; BIOS_SETDATE PROC FAR PUSHF ; Save status CLI ; Turn off interrupts MOV CS: BIOS_DATE,AX ; Save it POPF ; Restore status RET BIOS_SETDATE ENDP ; ; BIOS_SETTIME - Set the time ; ; CALL with: ; CH = hours (0-23) ; CL = minutes (0-59) ; DH = seconds (0-59) ; DL = hundredths of seconds (0-99) ; ; Uses: No registers are used ; BIOS_SETTIME PROC FAR PUSHF ; Save current status CLI ; Turn off interrupts MOV CS: BIOS_HRS,CH ; Save hours MOV CS: BIOS_MIN,CL ; Save minutes MOV CS: BIOS_SEC,DH ; Save seconds MOV CS: BYTE PTR BIOS_HSEC,DL ; Save hundredths of seconds POPF ; Restore status RET BIOS_SETTIME ENDP ; ; BIOS_GETDATE - Get time and date ; ; Returns: ; AX = count of days since Jan 1, 1980. ; CH = hours ; CL = minutes ; DH = seconds ; DL = hunderdths of seconds ; ; Uses: No registers are used ; BIOS_GETDATE PROC FAR PUSHF ; Save current status CLI ; Turn off interrupts MOV AX,CS: BIOS_DATE ; Get date MOV CH,CS: BIOS_HRS ; Get hours MOV CL,CS: BIOS_MIN ; Get minutes MOV DH,CS: BIOS_SEC ; Get seconds MOV DL,CS: BYTE PTR BIOS_HSEC ; Get hundredths of seconds POPF ; Restore status RET BIOS_GETDATE ENDP ; ; Date and time fields ; BIOS_DATE_TIME LABEL BYTE ; These fields must be together(see DEFMS) BIOS_DATE DW BIOS_RELDATE ; Days since 1980 BIOS_HRS DB 08 ; Hours since midnight BIOS_MIN DB 00 ; Minutes BIOS_SEC DB 0 ; Seconds BIOS_HSEC DW 0 ; Hundredths of seconds (needs to be a word) ALARM_FLAG DB 0 ; Alarm clock timer flag TICCNT DW 0 ; Tic counter PTICCNT DW 0 ; Previous tic counter value CW100 DW 100 ; Word constant 100 CB60 DB 60 ; Byte constant 60 PAGE ; ; ALARM_ST - Start alarm clock ; ; Call with: ; CX = tics before alarm goes off(a tic = 4 msec) ; ; Returns: ; Timer 2 starts running and ALARM_FLAG = FALSE ; ALARM_ST PROC NEAR CLI ; Disable interrupts MOV BYTE PTR CS:ALARM_FLAG,FALSE ; Show alarm hasn't gone off yet PUSH AX ; Save AX MOV AL,PITSC2+PITRLW+PITMITC ; Clear timer OUT ZTIMER+PITCW,AL MOV AL,NOT ZTIMERS2 ; Clear interrupt flag OUT ZTIMERS,AL MOV AL,CL ; Set clock period OUT ZTIMER+PITC2,AL MOV AL,CH OUT ZTIMER+PITC2,AL POP AX STI ; Restore interrupts RET ; and return ALARM_ST ENDP ; ; ALARM_CK - Check alarm and stop timer if alarm has gone off ; ; Returns: ; "CY" clear - alarm hasn't gone off yet ; "CY" set - alarm has gone off(and timer cleared) ; ALARM_CK PROC NEAR CLI ; Disable interrupts TEST BYTE PTR CS:ALARM_FLAG,TRUE ; Has alarm gone off ? JZ ALARM_CKR ; No, skip to end(CY is clear) STC ; Set CY to show alarm has gone off ALARM_CKST: PUSH AX ; Save AX MOV AL,PITSC2+PITRLW+PITMITC ; Get command to stop timmer 2 OUT ZTIMER+PITCW,AL ; Stop timmer POP AX ; Recover AX ALARM_CKR: STI ; Turn interrupts on RET ; and return ALARM_CK ENDP PAGE ; ; ALARM_SP - Stop Alarm clock ; ALARM_SP PROC NEAR CLI ; Disable interrupts JMP ALARM_CKST ; Join common code ALARM_SP ENDP ; ; ALARM_WAIT - Start alarm clock and wait for it to go off ; ; Call with: ; CX = tics before alarm goes off(a tic = 4 msec) ; ; Returns: ; Routine delays until the specified time has elapsed ; ALARM_WAIT PROC NEAR CALL ALARM_ST ; Start clock ALARM_WL: CALL ALARM_CK ; Has time elasped ? JNC ALARM_WL ; No, look again RET ; Yes, return ALARM_WAIT ENDP PAGE ; ; ISR_TIM - Interrupt service routine for timer ; ; Invoked when a timer interrupt occurs ; ; Updates time and date variables ; BIOS_DATE - days since Jan 1, 1980 ; BIOS_HR - hours since midnight ; BIOS_MN - minutes ; BIOS_SEC - seconds ; BIOS_HSEC - hundredths of seconds ; ; Updates disk drive variables(an deselect a drive) ; DSKT_FG - flag that drive is selected ; DSKT_DNCTR - down counter on select time ; DSKT_PORT - port to use to deselect drive ; DSKT_DSEL - command to deselect drive ; ISR_TIM: PUSH AX ; Save regs and set up DS PUSH DX PUSH DS MOV AX,CS MOV DS,AX ; Check cause of interrupt TIMINT1: IN AL,ZTIMERS ; Get cause of timer interrupt TEST AL,ZTIMERS0 ; Is it timer 0 ? JNZ TIM0INT ; Yes, go to it TEST AL,ZTIMERS2 ; Is it timer 2 ? JZ TIMINTX ; No, go handle it ; Handle timer 2 interrupts TIM2INT: OR BYTE PTR ALARM_FLAG,TRUE ; Set flag MOV AL,NOT ZTIMERS2 ; Clear intr OUT ZTIMERS,AL JMP SHORT TIMINT1 ; Go check for other interrupts ; Timer interrupt exit TIMINTX: MOV AL,OCW2OP+OCW2EOI OUT ZM8259A+OCW2,AL ; Tell 8259A that interrupt serviced POP DS ; Restore regs POP DX POP AX IRET ; and return ; Handle timer 0 interrupts TIM0INT: MOV AL,PITSC1+PITRLCL OUT ZTIMER+PITCW,AL ; Latch counter 1 value IN AL,ZTIMER+PITC1 ; Get counter 1's LSB MOV AH,AL ; Save it IN AL,ZTIMER+PITC1 ; Get counter 1's MSB XCHG AH,AL ; Swap bytes into proper regs NEG AX ; Take 2's complement MOV TICCNT,AX ; Save it as tic count ; (each tic is one hundredth of a sec) SUB AX,PTICCNT ; Compute elapsed tics TEST BYTE PTR DSKT_FG,0FFH ; Should disk deselect be looked at ? JZ TOD0 ; No, skip over SUB WORD PTR DSKT_DNCTR,AX ; Decr down counter, time out ? JG TOD0 ; No, skip MOV DX,DSKT_PORT ; Yes, get port number PUSH AX ; Save AX MOV AL,BYTE PTR DSKT_DSEL ; Get deselect command OUT DX,AL ; Deselect the drive MOV BYTE PTR DSKT_FG,00H ; Show disk deselected POP AX ; Recover AX TOD0: ; Execute user routine with tic in AX PUSH AX INT INT_UTMA ; Execute the interrupt routine CLI ; Insure that interrupts remain off POP AX ADD AX,BIOS_HSEC ; Compute new hundredths CMP AX,200 ; Did a lot of time go by(more than 2 sec)? JB TOD1 ; No, go handle the easy case XOR DX,DX ; Clear for divide DIV CW100 ; Word divide by 100 MOV BIOS_HSEC,DX ; Store remainder, which is hundredths of sec XOR DH,DH ; Clear high part MOV DL,BIOS_SEC ; Get seconds in DX ADD AX,DX ; Compute new seconds DIV CB60 ; Byte divide by 60 MOV BIOS_SEC,AH ; Store remainder, which is seconds ADD BIOS_MIN,AL ; Compute new minutes JMP SHORT TOD2 ; join back with other code TOD1: MOV BIOS_HSEC,AX ; Assume LT 100, Store hundredths SUB AX,100 ; Was assumption correct ? JB TOD3 ; Yes, value was ok - so not much to do MOV BIOS_HSEC,AX ; No, store correct value INC BIOS_SEC ; Bump seconds up MOV AL,BIOS_SEC ; Get seconds SUB AL,60 ; Did seconds go up to 60 JB TOD3 ; No, not much to do now MOV BIOS_SEC,AL ; Yes, store new value INC BIOS_MIN ; Bump minutes up TOD2: MOV AL,BIOS_MIN ; Get minutes SUB AL,60 ; Did minutes go up to or over 60 JB TOD3 ; No, not much to do MOV BIOS_MIN,AL ; Yes, store correct value INC BIOS_HRS ; Bump hours up CMP BIOS_HRS,24 ; Did hours go up to 24 JB TOD3 ; No, don't need to do any more MOV BIOS_HRS,0 ; Yes, fix it INC BIOS_DATE ; Bump days up TOD3: MOV AX,TICCNT ; Get tic counter MOV PTICCNT,AX ; Save it MOV AL,0FFH-ZTIMERS0 ; Clear intr OUT ZTIMERS,AL JMP TIMINT1 ; Check for more intrs ; ; Interrupt service routine for TIC timer ; ; Entry: AX = Number of 100th seconds since last call ; ; Exit: NONE ; ; Uses: NONE ; ; NOTE: Users trapping this interrupt should be sure that ; AX remains unchanged and that interrupts are left as is. ; The user routine should exit using a JMPF to the next routine ; in the interrupt list (found at 0:INT_UT) ; ISR_UTM: IRET ������������������������������������������������������������������������������������������